
function BaseTetris (engine)
{
  this.engine = engine;
    
  this.size = $V(1,1);
  
  this.blocks = 
  [
    [$V(0,0),$V(0,1),$V(1,1),$V(1,0)],     // Square
    [$V(0,0),$V(0,-1),$V(0,1),$V(0,2)],    // Straight
    [$V(0,0),$V(-1,0),$V(-1,1),$V(1,0)],   // L
    [$V(0,0),$V(-1,0),$V(-1,-1),$V(1,0)],  // Reverse L
    [$V(0,0),$V(-1,0),$V(0,-1),$V(1,-1)],  // S
    [$V(0,0),$V(-1,0),$V(0,1),$V(1,1)],    // Reverse S
    [$V(0,0),$V(-1,0),$V(1,0),$V(0,-1)]    // T
  ];
  
  this.colours = 
  [
    ['Red Block Main','Red Block Sub'],
    ['Green Block Main','Green Block Sub'],
    ['Blue Block Main','Blue Block Sub'],
    ['Yellow Block Main','Yellow Block Sub'],
    ['Purple Block Main','Purple Block Sub'],
    ['Cyan Block Main','Cyan Block Sub']
  ];
  
  this.rotationalMatrices = 
  [
    0,                                                    // No rotation
    (new Matrix22()).rotational(Math.PI / 2),             // 90
    (new Matrix22()).rotational(Math.PI),                 // 180
    (new Matrix22()).rotational(Math.PI * 1.5)            // 270
  ];
}

BaseTetris.prototype.drawSingleBlock = function (layer, colour, scale, point)
{
  this.engine.drawRect(layer,this.colours[colour][0],point,point.add(this.getSize(scale)));
  this.engine.drawRect(layer,this.colours[colour][1],point.add(this.getSize(scale).mul(0.25)),point.add(this.getSize(scale).mul(0.75)));
}

BaseTetris.prototype.drawBlock = function (layer, colour, block, rotation, scale, point)
{
  for(var i=0;i<this.blocks[block].length;i++)
  {
    var rotatedVector = this.rotateVector(rotation,this.blocks[block][i]);
    this.drawSingleBlock(layer,colour,scale,point.add(rotatedVector.mul(this.getSize(scale))));
  }  
}

BaseTetris.prototype.getSize = function (scale)
{
  return this.size.mul(scale);
}

BaseTetris.prototype.rotateVector = function (matrixId,point)
{
  if(matrixId == 0)
    return point;
  
  return this.rotationalMatrices[matrixId].mul(point).round();
}

BaseTetris.prototype.generateRandomColour = function ()
{
  return rand(0,this.colours.length);
}

BaseTetris.prototype.generateRandomBlock = function ()
{
  return rand(0,this.blocks.length);
}

BaseTetris.prototype.generateRandomRotation = function ()
{
  return rand(0,this.rotationalMatrices.length);
}


function Block(engine,block,colour,rotation,scale,position,layer)
{
  this.engine = engine;
  this.position = position;
  this.block = block;
  this.colour = colour;
  this.rotation = rotation;
  this.scale = scale;
  this.layer = layer;
}

Block.prototype.draw = function ()
{
  var tetris = new BaseTetris(this.engine);
  tetris.drawBlock(this.layer,this.colour,this.block,this.rotation,this.scale,this.position);
}

function FallingBlock(engine)
{
  var tetris = new BaseTetris(engine);
  var layerSize = engine.getTopLayer().size;
  Block.call(this,engine,
                  tetris.generateRandomBlock(),
                  tetris.generateRandomColour(),
                  tetris.generateRandomRotation(),
                  rand_f(10,20),
                  $V(rand(0,layerSize.x),layerSize.y + 50),
                  0);
  
  this.velocity = $V(0,rand(-50,-100));
  this.freeRotationalSpeed = rand_f(-Math.PI * 1.5, Math.PI * 1.5);
  this.freeRotation = rand_f(0,Math.PI * 2);
}

FallingBlock.inherit(Block);

FallingBlock.prototype.draw = function ()
{
  this.engine.save(this.layer);
  
  this.engine.translate(this.layer,this.position);
  
  this.engine.rotate(this.layer,this.freeRotation);
  
  var tetris = new BaseTetris(this.engine);
  tetris.drawBlock(this.layer,this.colour,this.block,this.rotation,this.scale,$V(0,0));
  
  this.engine.restore(this.layer);
}

FallingBlock.prototype.update = function (timeChange)
{
  var unitTimeChange = timeChange / 1000.0;
  this.position = this.position.add(this.velocity.mul(unitTimeChange));
  this.freeRotation = (this.freeRotation + (this.freeRotationalSpeed * unitTimeChange)) % (Math.PI * 2);
}


function SceneMenu (engine)
{
  Scene.call(this,engine);
  this.drawInterval = null;
  this.logicTimeout = null;
  this.blocks = Array();
}

SceneMenu.inherit(Scene);

SceneMenu.prototype.build = function (engine)
{
  engine.addStyle('Red Block Main',new FillStrokeStyle(rgb(255,0,0),rgb(0,0,0),1));
  engine.addStyle('Red Block Sub',new FillStrokeStyle(rgb(255,50,50),rgb(0,0,0),1));
  engine.addStyle('Green Block Main',new FillStrokeStyle(rgb(0,255,0),rgb(0,0,0),1));
  engine.addStyle('Green Block Sub',new FillStrokeStyle(rgb(50,255,50),rgb(0,0,0),1));
  engine.addStyle('Blue Block Main',new FillStrokeStyle(rgb(0,0,255),rgb(0,0,0),1));
  engine.addStyle('Blue Block Sub',new FillStrokeStyle(rgb(50,50,255),rgb(0,0,0),1));
  engine.addStyle('Yellow Block Main',new FillStrokeStyle(rgb(255,255,0),rgb(0,0,0),1));
  engine.addStyle('Yellow Block Sub',new FillStrokeStyle(rgb(255,255,50),rgb(0,0,0),1));
  engine.addStyle('Purple Block Main',new FillStrokeStyle(rgb(255,0,255),rgb(0,0,0),1));
  engine.addStyle('Purple Block Sub',new FillStrokeStyle(rgb(255,50,255),rgb(0,0,0),1));
  engine.addStyle('Cyan Block Main',new FillStrokeStyle(rgb(0,255,255),rgb(0,0,0),1));
  engine.addStyle('Cyan Block Sub',new FillStrokeStyle(rgb(50,255,255),rgb(0,0,0),1));  
  
  engine.addImage('title','Images/title.png');
  
  this.playButton = new SceneImageButton(engine,'play',null,'Images/title2.png','Images/title.png',$V(100,100),$V(200,150));
  
  this.engine.setTransformMatrix(0,1,0,0,-1,0,this.engine.getTopLayer().size.y);
  this.engine.getLayer(1).context.setTransform(1,0,0,-1,0,this.engine.getTopLayer().size.y);
  //this.engine.setTransformMatrix(1,1,0,0,-1,0,this.engine.getTopLayer().size.y);
}

SceneMenu.prototype.destroy = function (engine)
{
  clearInterval(this.drawInterval);
  clearTimeout(this.logicTimeout);  
}

SceneMenu.prototype.main = function (engine)
{
  this.drawInterval = setInterval(bind(this,this.draw),1);
  this.logic();
  this.draw();
}

SceneMenu.prototype.draw = function ()
{
  var timeChange = this.getTimeChange();
    
  this.engine.clearRect(1,$V(0,0),$V(640,480));
  this.engine.drawImage(1,'title',$V(100,100),$V(200,150));
  /*
  for(var i=0;i<this.blocks.length;i++)
  {
    this.blocks[i].update(timeChange);
    
    if(this.blocks[i].position.y < -50)
    {
      this.blocks.splice(i,1);
      i--;
      continue;
    }
    
    this.blocks[i].draw();    
  }
  
  this.engine.clearRect(1,$V(0,0),$V(640,480));
  
  this.playButton.draw();
  */
}

SceneMenu.prototype.logic = function ()
{
  this.blocks.push(new FallingBlock(this.engine));
  this.logicTimeout = setTimeout(bind(this,this.logic),rand(250,500));
}

SceneMenu.prototype.drawTestPattern = function()
{
  var xOffset = $V(0,0);
  for(var i=0;i<this.blocks.length;i++)
  {
    xOffset = xOffset.add($V(40,0));
    var yOffset = xOffset.clone();  
    for(var j=0;j<this.rotationalMatrices.length;j++)
    {
      yOffset = yOffset.add($V(0,40));
      this.drawBlock(1,this.generateRandomColour(),i,j,yOffset);
    }
  }  
}

function main()
{
/*  var m1 = new Matrix33();
  var m2 = new Matrix33();
  //m2 = m2.rotation(Math.PI / 2);
  //m2 = m2.translation($V(50,50));
  m2 = m2.scale($V(2,2));
  m1 = m1.mul(m2);
  
  var v1 = new Vector2(1,0);    
  var s = m1.mul(v1);
  
  return;*/

  var engine = new Engine();
  engine.addLayer('bg');
  engine.addLayer('fg');
  engine.addClickLayer('click');
  
  engine.setupInteraction();
  
  var menu = new SceneMenu(engine);
  
  menu.start();
  engine.startInteraction();
  /*
  engine.addStyle('Red Block Main',new FillStrokeStyle(rgb(255,0,0),rgb(0,0,0),1));
  engine.setTransformMatrix(0,1,0,0,-1,0,engine.getTopLayer().size.y);
  engine.translate(0,$V(50,50));
  engine.rotate(0,Math.PI/4);
  engine.drawRect(0,'Red Block Main',$V(0,0),$V(10,10));
  */
  return;
}
